#include<iostream>
#include<semaphore.h>
#include<pthread.h>
#include<vector>

#define NUM 10

template<class T>
class RingQueue
{
private:
    int _cap;//容量
    std::vector<T> _rq;//临界资源
    //保证消费者和生产者之间的同步与互斥关系
    sem_t _space;//描述空间资源
    sem_t _data;//描述数据资源
    //记录下标位置-同样也是一种临界资源
    int c_index;
    int p_index;
    //保证多线程下消费者之间和生产者之间的互斥关系（使用的下标是临界资源，并且对下标的操作不是原子的）
    pthread_mutex_t c_lock;
    pthread_mutex_t p_lock;
public:
    RingQueue(int cap=NUM):_cap(cap),_rq(cap)
    {
        sem_init(&_space,0,_cap);
        sem_init(&_data,0,0);
        pthread_mutex_init(&c_lock,nullptr);
        pthread_mutex_init(&p_lock,nullptr);
    }
    ~RingQueue()
    {
        sem_destroy(&_space);
        sem_destroy(&_data);
        pthread_mutex_destroy(&c_lock);
        pthread_mutex_destroy(&p_lock);
    }
    void Put(const T& in)
    {
        sem_wait(&_space);//申请空间资源-预定
        pthread_mutex_lock(&c_lock);//生产者之间竞争互斥锁-排队
        _rq[c_index++]=in;
        c_index%=_cap;
        sem_post(&_data);//发布数据资源
        pthread_mutex_unlock(&c_lock);//解锁
    }
    void Get(T* out)
    {
        sem_wait(&_data);//申请数据资源
        pthread_mutex_lock(&p_lock);//消费者竞争互斥锁-排队
        *out=_rq[p_index++];
        p_index%=_cap;
        sem_post(&_space);//发布空间资源
        pthread_mutex_unlock(&p_lock);//解锁
    }
};
